//----------------------------------------------------------------------------
//  ,-.
// /_\___ ,   Ninja Framework
// '  ___\    (C) Riccardo Capra - http://riccar.do
//  //   \\
//----------------------------------------------------------------------------
//  This program is free software: you can redistribute it and/or modify
//  it under the terms of the GNU General Public License as published by
//  the Free Software Foundation, either version 3 of the License, or
//  (at your option) any later version.
//
//  This program is distributed in the hope that it will be useful,
//  but WITHOUT ANY WARRANTY; without even the implied warranty of
//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
//  GNU General Public License for more details.
//
//  You should have received a copy of the GNU General Public License
//  along with this program.  If not, see <http://www.gnu.org/licenses/>.
//----------------------------------------------------------------------------

#include "NjExample01.h"
#include "NjLocklessRandGenerator.h"

//----------------------------------------------------------------------------
class NjLocklessRandGenerator::Static
{
public:
#if NJ_PLATFORM_64_BIT
	static NjUint const MULTIPLIER = 6364136223846793005ULL;
	static NjUint const INCREMENT = 1442695040888963407ULL;
#else // NJ_PLATFORM_64_BIT
	static NjUint const MULTIPLIER = 1664525;
	static NjUint const INCREMENT = 1013904223;
#endif // NJ_PLATFORM_64_BIT

	static NjAtomic<NjUint> m_kSeed;

	NJ_DISABLE_INSTANCE(Static);
};
//----------------------------------------------------------------------------
NjUint NjLocklessRandGenerator::GetSeed()
{
	return Static::m_kSeed.Get();
}
//----------------------------------------------------------------------------
void NjLocklessRandGenerator::SetSeed(NjUint uSeed)
{
	Static::m_kSeed.Set(uSeed);
}
//----------------------------------------------------------------------------
NjUint NjLocklessRandGenerator::Next()
{
	NjUint uValue(Static::m_kSeed.Get());

	for(;;)
	{
		NjUint const uNewValue(uValue*Static::MULTIPLIER+Static::INCREMENT);
		NjUint const uOldValue(Static::m_kSeed.PostCompareExchange(uValue, uNewValue));

		if (uOldValue==uValue)
			return uNewValue;

		uValue=uOldValue;
	}
}
//----------------------------------------------------------------------------
NjAtomic<NjUint> NjLocklessRandGenerator::Static::m_kSeed(0);
//----------------------------------------------------------------------------
